package com.cheetah.handler;

import com.cheetah.annotation.Handler;
import com.cheetah.config.ServerConfig;
import com.cheetah.protocol.codec.CheetahDecoder;
import com.cheetah.protocol.codec.CheetahEncoder;
import com.cheetah.protocol.codec.CheetahHeartbeatEncoder;
import io.netty.channel.*;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.timeout.IdleStateHandler;
import io.netty.util.concurrent.DefaultEventExecutorGroup;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Component
@Slf4j
public class NettyHandlerInitializer extends ChannelInitializer<SocketChannel> implements ApplicationContextAware {

	private ApplicationContext applicationContext;

    @Autowired
    private ServerConfig serverConfig;

	private DefaultEventExecutorGroup executor = null;

	private List<Object> list;

	@PostConstruct
	public void init(){
		//executor = new DefaultEventExecutorGroup(serverConfig.getHandlerDispatchThread(), new DefaultThreadFactory("messageHandler"));
		Map<String,Object> beans = applicationContext.getBeansWithAnnotation(Handler.class);

		list = new ArrayList<>(beans.values());

		list.sort((o1,o2) ->
				o1.getClass().getAnnotation(Handler.class).order()
						- o2.getClass().getAnnotation(Handler.class).order());

		list.forEach(k -> {
			Handler handler = k.getClass().getAnnotation(Handler.class);
			log.info("init channel handler [{}],order [{}],sharable [{}]",k.getClass().getSimpleName(),handler.order(),handler.sharable());
		});
	}

	@Override
	protected void initChannel(SocketChannel ch) throws Exception {

		ChannelPipeline pip = ch.pipeline()
				.addLast(new IdleStateHandler(60 * 5, 0, 0, TimeUnit.SECONDS))
				.addLast(new CheetahDecoder())
				.addLast(new CheetahHeartbeatEncoder())
				.addLast(new CheetahEncoder());
		list.forEach(k -> {
			if(k instanceof ChannelHandler){
				log.info("add channel handler [{}]",k.getClass().getSimpleName());
				pip.addLast(k.getClass().getSimpleName(),(ChannelHandler)k);
			}
		});
	}

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		this.applicationContext = applicationContext;
	}
}
